home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / Telephone Manager / Stiletto Sources / Sources / LogWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-05  |  28.2 KB  |  1,115 lines  |  [TEXT/MPS ]

  1. /************************************************************************************************/
  2. /*                                                                                                */
  3. /*    Program Name:    Stiletto                                                                    */
  4. /*                                                                                                */
  5. /*    File Name:        LogWindow.c                                                                    */
  6. /*                                                                                                */
  7. /*    © Apple Computer, Inc. 1991-1995                                                            */
  8. /*    All Rights Reserved                                                                            */
  9. /*                                                                                                */
  10. /*    Revision History:                                                                            */
  11. /*                                                                                                */
  12. /*        Date        Who                    Modification                                            */
  13. /*                                                                                                */
  14. /*        1991-06-11    Chris Halim            Original version                                        */
  15. /*        1995-06-26    Jaakko Railo        Version 2.0                                                */
  16. /*                                                                                                */
  17. /************************************************************************************************/
  18.  
  19. /****************************************** DESCRIPTION ******************************************
  20.  
  21. *************************************************************************************************/
  22.  
  23. /******************************************** HEADERS *******************************************/
  24.  
  25. #include "Resources.h"
  26. #include "StandardFile.h"
  27. #include "stdarg.h"
  28. #include "stdio.h"
  29. #include "string.h"
  30. #include "Strings.h"
  31. #include "ToolUtils.h"
  32.  
  33. #include "flstUtilities.h"
  34. #include "LogWindow.h"
  35. #include "Utilities.h"            // we use AlertUser()
  36.  
  37. /****************************************** DEFINITIONS *****************************************/
  38.  
  39. #define    kTopMargin        21
  40. #define kTextMargin        2
  41. #define    kStrBufferSize    512
  42.  
  43. #if defined(powerc) || defined (__powerc)
  44. #pragma options align=mac68k
  45. #endif
  46. struct LWINRec {
  47.     short    numOfLines;
  48.     short    maxWidth;
  49.     short    minWidth;
  50. };
  51. #if defined(powerc) || defined(__powerc)
  52. #pragma options align=reset
  53. #endif
  54.  
  55. typedef struct LWINRec LWINRec;
  56.  
  57. typedef LWINRec *LWINRecPtr, **LWINRecHandle;
  58.  
  59. /****************************************** PROTOTYPES ******************************************/
  60.  
  61. void    DrawLogWindow (WindowPtr theWindow);
  62. void    DoLogWindowActivate (WindowPtr theWindow, Boolean becomingActive);
  63. void    DoLogWindowUpdate (WindowPtr theWindow);
  64. void    DoLogWindowOSEvent (const EventRecord *theEvent);
  65. void     DoLogWindowSuspend (Boolean doClipConvert);
  66. void     DoLogWindowResume (Boolean doClipConvert);
  67. Boolean    DoLogWindowMouseDown (const EventRecord *theEvent);
  68. void    DoLogWindowClick (WindowPtr theWindow, const EventRecord * theEvent);
  69. void    DoLogWindowGrow (WindowPtr theWindow, const EventRecord * theEvent);
  70. void    DoLogWindowZoom (WindowPtr theWindow, short part);
  71.  
  72. void    TELiteScroll (LogWindowPtr logWindow, short value);
  73.  
  74. TELiteHandle    CreateNewTELite (Boolean colorPort);
  75. void        GetTERect (WindowPtr theWindow, Rect * theRect);
  76. void         AdjustHV (Boolean isVert, ControlHandle control, TELiteHandle theTELite, Boolean canRedraw);
  77. void        AdjustScrollValues (LogWindowPtr logWindow, Boolean canRedraw);
  78. void         AdjustScrollSizes (LogWindowPtr logWindow);
  79. void         AdjustScrollbars (LogWindowPtr logWindow,Boolean needsResize);
  80. void        ShowGrowIcon (WindowPtr theWindow);
  81. void        AdjustHeight (short * height, LogWindowPtr    logWindow);
  82.  
  83. void        CommonAction (ControlHandle theControl, short * amount);
  84. void        DrawFromOffscreen (LogWindowPtr logWindow);
  85.  
  86. Boolean        FillFSSpec (LogWindowPtr logWindow);
  87. void        AppendLine (LogWindowPtr logWindow, const char * cStr);
  88.  
  89. void         PutTextToLogWindow (LogWindowPtr logWindow, const char * cStr);
  90.  
  91. /******************************************** GLOBALS *******************************************/
  92.  
  93. extern    ControlActionUPP    gVActionProcUPP;
  94.  
  95. /************************************************************************************************/
  96. /************************************************************************************************/
  97.  
  98.  
  99. #pragma segment LogWindowSeg
  100. short    CreateLogWindow (LogWindowPtr * logWindow, const Rect * windowRect)
  101. {
  102.     WindowPtr    savedPort;
  103.     Ptr            tPtr;
  104.     Rect        boundsRect;
  105.     short        height;
  106.     RgnHandle    grayRgn;
  107.     
  108.     /**
  109.      **        Create storage for the window record. We will pass this to GetNewWindow().
  110.      **
  111.      **/
  112.      
  113.     tPtr = NewPtr (sizeof (LogWindowRec));
  114.     if (tPtr == nil) {
  115.         AlertUser ("\pNot enough memory to create log window !", MemError ());
  116.         return (-1);
  117.     }
  118.     
  119.     /**
  120.      **        Get a "WIND" resource for the log window.
  121.      **
  122.      **/
  123.      
  124.     if (HasColorQD())
  125.         *logWindow = (LogWindowPtr) GetNewCWindow (rLogWIND, tPtr, (WindowPtr)(-1L));
  126.     else
  127.         *logWindow = (LogWindowPtr) GetNewWindow (rLogWIND, tPtr, (WindowPtr)(-1L));
  128.     
  129.     if (*logWindow == nil) {
  130.         AlertUser ("\pUnable to get a WIND resource for log window!", ResError ());
  131.         DisposPtr (tPtr);
  132.         return (-1);
  133.     }
  134.     
  135.     /**
  136.      **        Move and resize the window according to the rect passed in windowRect.
  137.      **        Also make sure that the window is within the screen boundary.
  138.      **
  139.      **/
  140.     
  141.     grayRgn = GetGrayRgn ();
  142.     if (windowRect && !EmptyRect(windowRect) && RectInRgn (windowRect, grayRgn)) {
  143.         MoveWindow ((WindowPtr) *logWindow, windowRect->left, windowRect->top, false);
  144.         height = windowRect->bottom - windowRect->top;
  145.         SizeWindow ((WindowPtr) *logWindow, windowRect->right - windowRect->left,
  146.                         height, true);
  147.     }
  148.     
  149.     /**
  150.      **        Set the window's characteristics.
  151.      **
  152.      **/
  153.      
  154.     GetPort (&savedPort);
  155.     SetPort ((WindowPtr) *logWindow);
  156.     TextSize (9);
  157.     SetPort (savedPort);
  158.     
  159.     /** 
  160.      **        Create a new vertical control scroll.
  161.      **
  162.      **/
  163.      
  164.     boundsRect = ((WindowPtr) tPtr)->portRect;
  165.     boundsRect.top += kTopMargin - 1;
  166.     ++boundsRect.right;
  167.     boundsRect.bottom -= 14;
  168.     boundsRect.left = boundsRect.right - 16;
  169.     ((LogWindowPtr) tPtr)->vScroll = NewControl ((WindowPtr) tPtr, &boundsRect,
  170.             "\pvScroll", true, 0, 0, 0, scrollBarProc, 0);
  171.     
  172.     /** 
  173.      **        Get checkBox & button from resource.
  174.      **
  175.      **/
  176.      
  177.     ((LogWindowPtr) tPtr)->saveCheckBox = GetNewControl (rSaveCheckBoxCNTL,(WindowPtr) tPtr);
  178.     ((LogWindowPtr) tPtr)->clearLogButton = GetNewControl (rClearLogButtonCNTL,(WindowPtr) tPtr);
  179.  
  180.     /**
  181.      **        Create a TELiteHandle for the the log window.
  182.      **
  183.      **/
  184.      
  185.     if (((*logWindow)->fTELiteHandle = CreateNewTELite (false)) == nil)
  186.         return (-1);
  187.     
  188.     (*(LogWindowPtr) tPtr).logFileSpec = nil;
  189.     (*(LogWindowPtr) tPtr).saveToDisk = false;
  190.     
  191.     ShowWindow ((WindowPtr) *logWindow);
  192.     
  193.     return (noErr);
  194. }
  195.  
  196.  
  197. #pragma segment LogWindowSeg
  198. Boolean    IsHandledByLogWindow (LogWindowPtr logWindow, const EventRecord * theEvent)
  199. {
  200.     WindowPtr    theWindow;
  201.     Boolean        wasHandled = false;
  202.     
  203.     if (logWindow != nil) {
  204.         switch ( theEvent->what ) {
  205.             case mouseDown:
  206.                 (void) FindWindow(theEvent->where, &theWindow);
  207.                 if (theWindow == (WindowPtr) logWindow) {
  208.                     wasHandled = DoLogWindowMouseDown (theEvent);
  209.                 }
  210.                 break;
  211.                             
  212.             case activateEvt:
  213.                 if ((LogWindowPtr) theEvent->message == logWindow) {
  214.                     DoLogWindowActivate ((WindowPtr) logWindow, (theEvent->modifiers & activeFlag) != 0);
  215.                     wasHandled = true;
  216.                 }
  217.                 break;
  218.                 
  219.             case updateEvt:
  220.                 if ((LogWindowPtr) theEvent->message == logWindow) {
  221.                     DoLogWindowUpdate ((WindowPtr) logWindow);
  222.                     wasHandled = true;
  223.                 }
  224.                 break;
  225.                 
  226.             case osEvt:
  227.                 if ((LogWindowPtr) FrontWindow () == logWindow) {
  228.                     DoLogWindowOSEvent (theEvent);
  229.                     wasHandled = false;                    // we want main program to still handle osevt
  230.                                                         // it may want to convert scrap etc.
  231.                 }
  232.                 break;
  233.         }
  234.     }
  235.     
  236.     return (wasHandled);
  237. }
  238.  
  239.  
  240. #pragma segment LogWindowSeg
  241. void    DoLogWindowOSEvent (const EventRecord *theEvent)
  242. {
  243.     Boolean    doConvert;
  244.     unsigned char evType;
  245.  
  246.     evType = (unsigned char) (theEvent->message >> 24) & 0x00ff; // Get the high byte.
  247.     switch (evType) {                     // The high byte of message is the type of event.
  248.         case suspendResumeMessage :
  249.             doConvert = (theEvent->message & convertClipboardFlag) != 0;
  250.             
  251.             if ((theEvent->message & resumeFlag) == 0)
  252.               DoLogWindowSuspend (doConvert);
  253.               
  254.             else DoLogWindowResume (doConvert);
  255.             break;
  256.     }
  257. }
  258.  
  259.  
  260. #pragma segment LogWindowSeg
  261. void     DoLogWindowSuspend (Boolean doClipConvert)
  262. {
  263. #pragma unused (doClipConvert)
  264.  
  265.     DoLogWindowActivate (FrontWindow(), false);
  266. }
  267.  
  268.  
  269. #pragma segment LogWindowSeg
  270. void     DoLogWindowResume (Boolean doClipConvert)
  271. {
  272. #pragma unused (doClipConvert)
  273.  
  274.     InitCursor ();
  275.     DoLogWindowActivate (FrontWindow(), true);
  276. }
  277.  
  278.  
  279. #pragma segment LogWindowSeg
  280. Boolean    DoLogWindowMouseDown (const EventRecord *theEvent)
  281. {
  282.     short        part;
  283.     WindowPtr    theWindow;
  284.     Boolean        wasHandled = false;
  285.     
  286.     part = FindWindow(theEvent->where, &theWindow);
  287.     switch ( part ) {            
  288.         case inContent:
  289.             if ( theWindow != FrontWindow() ) {
  290.                 SelectWindow(theWindow);
  291.             } else
  292.                 DoLogWindowClick (theWindow, theEvent);
  293.                 
  294.             wasHandled = true;
  295.             break;
  296.             
  297.         case inDrag:        // pass screenBits.bounds to get all gDevices
  298.             if (!(theEvent->modifiers & cmdKey))    // if command key isn't down
  299.                 SelectWindow (theWindow);
  300.                 
  301.             DragWindow (theWindow, theEvent->where, &qd.screenBits.bounds);
  302.                 
  303.             wasHandled = true;
  304.             break;
  305.             
  306.         case inGoAway:
  307.             if ( TrackGoAway (theWindow, theEvent->where) )
  308.                 HideWindow (theWindow);
  309.             wasHandled = true;
  310.             break;
  311.             
  312.         case inGrow:
  313.             DoLogWindowGrow (theWindow, theEvent);
  314.             wasHandled = true;
  315.             break;
  316.             
  317.         case inZoomIn:
  318.         case inZoomOut:
  319.             if ( TrackBox (theWindow, theEvent->where, part) )
  320.                 DoLogWindowZoom (theWindow, part);
  321.                 
  322.             wasHandled = true;
  323.             break;
  324.     }
  325.     
  326.     return (wasHandled);
  327. }
  328.  
  329.  
  330. #pragma segment LogWindowSeg
  331. TELiteHandle    CreateNewTELite (Boolean colorPort)
  332. {
  333.     GrafPtr            savedPort, tPort;
  334.     BitMap            *tBitMapPtr;
  335.     short            rowBytes, width, height, lineHeight;
  336.     TELiteHandle    theTELite;
  337.     TextState         textInfo;
  338.     FontInfo        tPortFontInfo;
  339.     LWINRecHandle    lwinResource;
  340.         
  341.     lwinResource = (LWINRecHandle) Get1Resource ('LWIN', rLogLWIN);
  342.     if (lwinResource == nil) {
  343.         AlertUser ("\pUnable to retrieve the needed resource", MemError ());
  344.         return (nil);
  345.     }
  346.  
  347.     /**
  348.      **        Create the offscreen port.
  349.      **
  350.      **/
  351.     
  352.     if (colorPort)
  353.         tPort = (GrafPtr) NewPtr (sizeof (CGrafPort));
  354.     else
  355.         tPort = (GrafPtr) NewPtr (sizeof (GrafPort));
  356.         
  357.     if (tPort == nil) {
  358.         AlertUser ("\pCan't allocate memory for our offscreen port", MemError ());
  359.         ReleaseResource ((Handle) lwinResource);
  360.         return (nil);
  361.     }
  362.  
  363.     GetPort (&savedPort);
  364.     
  365.     if (colorPort)
  366.         OpenCPort ((CGrafPtr) tPort);
  367.     else
  368.         OpenPort (tPort);
  369.  
  370.     SetPort (tPort);
  371.     
  372.     GetIndflst (rLogWindowflst, 1, &textInfo);
  373.     TextFont (textInfo.theFont);
  374.     TextFace (textInfo.theFace);
  375.     TextSize (textInfo.theSize);
  376.     TextMode (textInfo.theMode);
  377.     
  378.     GetFontInfo (&tPortFontInfo);
  379.     lineHeight = tPortFontInfo.ascent + tPortFontInfo.descent + tPortFontInfo.leading;
  380.     
  381.     /**
  382.      **        Create the bitmap to be used by our offscreen port.
  383.      **
  384.      **/
  385.      
  386.     width = (*lwinResource)->maxWidth;
  387.     height = lineHeight * (*lwinResource)->numOfLines;    // maxLines * lineHeight;
  388.         
  389.     rowBytes = ((width + 15) / 16) * 2;
  390.     tBitMapPtr = (BitMap*) NewPtrClear ((long) rowBytes * height + sizeof (BitMap));
  391.     if (tBitMapPtr == nil) {
  392.         AlertUser ("\pCan't allocate memory for our offscreen BitMap", MemError ());
  393.         DisposPtr ((Ptr) tPort);
  394.         ReleaseResource ((Handle) lwinResource);
  395.         return (nil);
  396.     }
  397.     
  398.     tBitMapPtr->rowBytes = rowBytes;
  399.     tBitMapPtr->baseAddr = (Ptr) (tBitMapPtr + 1);
  400.     SetRect(&tBitMapPtr->bounds, 0, 0, width, height);
  401.     
  402.     SetPortBits (tBitMapPtr);
  403.     PortSize (width, height);
  404.     SetOrigin (0, 0);
  405.     ClipRect (&tBitMapPtr->bounds);
  406.     RectRgn (tPort->visRgn, &tBitMapPtr->bounds);
  407.  
  408.     SetPort (savedPort);
  409.     
  410.     /**
  411.      **        Create the TELiteHandle requested by the calling function.
  412.      **
  413.      **/
  414.     
  415.     theTELite = (TELiteHandle) NewHandle (sizeof (TELiteRec));
  416.     if (theTELite == nil) {
  417.         AlertUser ("\pCan't allocate memory for our text edit lite", MemError ());
  418.         DisposPtr ((Ptr) tBitMapPtr);
  419.         DisposPtr ((Ptr) tPort);
  420.         ReleaseResource ((Handle) lwinResource);
  421.         return (nil);
  422.     }
  423.  
  424.     (**theTELite).offScreenPort = tPort;
  425.     (**theTELite).lineHeight = lineHeight;
  426.     (**theTELite).fontAscent = tPortFontInfo.ascent;
  427.     (**theTELite).maxLines = (*lwinResource)->numOfLines;
  428.     (**theTELite).minWidth = (*lwinResource)->minWidth;
  429.     (**theTELite).numOfLines = 0;
  430.     (**theTELite).top = 0;
  431.     (**theTELite).left = 0;
  432.     
  433.     ReleaseResource ((Handle) lwinResource);
  434.     return    (theTELite);
  435. }
  436.  
  437.  
  438. #pragma segment LogWindowSeg
  439. void    DoLogWindowClick (WindowPtr theWindow, const EventRecord * theEvent)
  440. {
  441.     short            part, value;
  442.     ControlHandle    theControl;
  443.     Point            mousePos;
  444.     WindowPtr        savedPort;
  445.     Rect            teRect;
  446.     
  447.     GetPort    (&savedPort);
  448.     SetPort (theWindow);
  449.     
  450.     mousePos = theEvent->where;
  451.     GlobalToLocal (&mousePos);
  452.     
  453.     GetTERect (theWindow, &teRect);
  454.     
  455.     if (PtInRect (mousePos, &teRect))
  456.     {
  457.     }
  458.     else
  459.     {
  460.         part = FindControl (mousePos, theWindow, &theControl);
  461.         switch (part) {
  462.             case 0 :        // invisible or inactive control was clicked
  463.                 break;
  464.             
  465.             case inThumb :
  466.                 value = GetCtlValue (theControl);
  467.                 part = TrackControl (theControl, mousePos, nil);
  468.                 if (part != 0) {
  469.                     value -= GetCtlValue (theControl);
  470.                         
  471.                     if (value != 0)
  472.                         TELiteScroll ((LogWindowPtr) theWindow, value);
  473.                 }
  474.                 break;
  475.             
  476.             case inButton:
  477.                 part = TrackControl (theControl, mousePos, nil);
  478.                 if (part != 0) {
  479.                     ClearLogWindow ((LogWindowPtr) theWindow);
  480.                 }
  481.                 break;
  482.             
  483.             case inCheckBox:
  484.                 part = TrackControl (theControl, mousePos, nil);
  485.                 if (part != 0) {
  486.                     ((LogWindowPtr) theWindow)->saveToDisk = 
  487.                         value = (GetCtlValue (theControl)) ? false : true;
  488.                     SetCtlValue (theControl, value);
  489.                     if ((value != 0) && (((LogWindowPtr) theWindow)->logFileSpec == nil))
  490.                         if (FillFSSpec ((LogWindowPtr) theWindow) == false) {
  491.                             SetCtlValue (theControl, false);
  492.                             ((LogWindowPtr) theWindow)->saveToDisk = false;
  493.                         }
  494.                 }
  495.                 break;
  496.                 
  497.             default :
  498.                 value = TrackControl (theControl, mousePos, gVActionProcUPP);
  499.         }
  500.     }
  501.     
  502.     SetPort (savedPort);
  503. }
  504.  
  505.  
  506. #pragma segment LogWindowSeg
  507. Boolean    FillFSSpec (LogWindowPtr logWindow)
  508. {
  509.     OSErr        errCode;
  510.     Rect        nameRect;
  511.     WindowPtr    savedPort;
  512.     DateTimeRec    date;
  513.     Str255        tStr;
  514.     StandardFileReply theReply;
  515.     CursHandle     watch = GetCursor(watchCursor);
  516.     
  517.     if (watch != nil) SetCursor (*watch);
  518.     
  519.     GetTime (&date);
  520.     sprintf ((char *) tStr,"%02d.%02d.%02d-%02d.%02d.%02d", date.month, date.day, date.year,
  521.             date.hour, date.minute, date.second);
  522.     c2pstr ((char *) tStr);
  523.  
  524.     StandardPutFile ("\pSave log to :", tStr, &theReply);
  525.     
  526.     if (theReply.sfGood) {
  527.         
  528.         if (theReply.sfReplacing) {
  529.             errCode = FSpDelete(&theReply.sfFile);
  530.             if (errCode != noErr) {
  531.                 AlertUser ("\pUnable to delete the file.", errCode);
  532.                 return (false);
  533.             }
  534.         }
  535.  
  536.         errCode = FSpCreate (&theReply.sfFile, 'ttxt', 'TEXT', theReply.sfScript);
  537.         if (errCode != noErr) {
  538.             AlertUser ("\pUnable to create the specified file.", errCode);
  539.             return (false);
  540.         }
  541.  
  542.         if (logWindow->logFileSpec == nil)
  543.             logWindow->logFileSpec = (FSSpecHandle) NewHandle (sizeof (FSSpec));
  544.         
  545.         (**logWindow->logFileSpec) = theReply.sfFile;
  546.         
  547.         GetPort (&savedPort);
  548.         SetPort ((WindowPtr) logWindow);
  549.         nameRect = ((WindowPtr) logWindow)->portRect;
  550.         nameRect.bottom = nameRect.top + kTopMargin - 3;
  551.         InvalRect (&nameRect);
  552.         SetPort (savedPort);
  553.     } else {
  554.     }
  555.     
  556.     SetCursor (&qd.arrow);
  557.     return (theReply.sfGood);
  558. }
  559.  
  560.  
  561. #pragma segment LogWindowSeg
  562. pascal void    VActionProc (ControlHandle theControl, short part)
  563. {
  564.     short            amount;
  565.     LogWindowPtr    logWindow;
  566.     TELitePtr        tTELite;
  567.     Rect            viewRect;
  568.     
  569.     if (part != 0) {
  570.         logWindow =  (LogWindowPtr) (*theControl)->contrlOwner;
  571.         tTELite = *logWindow->fTELiteHandle;
  572.         
  573.         switch (part) {
  574.             case inUpButton :
  575.             case inDownButton :
  576.                 amount = 1;
  577.                 break;
  578.             case inPageUp :
  579.             case inPageDown :
  580.                 GetTERect ((WindowPtr) logWindow, &viewRect);
  581.                 amount = (viewRect.bottom - viewRect.top) / tTELite->lineHeight;
  582.                 break;
  583.         }
  584.         if ((part == inDownButton) || (part == inPageDown))
  585.             amount = -amount;
  586.         
  587.         CommonAction (theControl, &amount);
  588.         
  589.         if (amount != 0)
  590.             TELiteScroll (logWindow, amount);
  591.     }
  592. }
  593.  
  594.  
  595. #pragma segment LogWindowSeg
  596. void    CommonAction (ControlHandle theControl, short * amount)
  597. {
  598.     short    value, max;
  599.     
  600.     value = GetCtlValue (theControl);
  601.     max = GetCtlMax (theControl);
  602.     *amount = value - *amount;
  603.     if (*amount < 0)
  604.         *amount = 0;
  605.     else if (*amount > max)
  606.         *amount = max;
  607.     
  608.     SetCtlValue (theControl, *amount);
  609.     *amount = value - *amount;
  610. }
  611.  
  612.  
  613. #pragma segment LogWindowSeg
  614. void    DrawFromOffscreen (LogWindowPtr logWindow)
  615. {
  616.     WindowPtr        savedPort;
  617.     BitMap            tBitMap;
  618.     TELiteHandle    tTELite;
  619.     Rect            offScreenRect;
  620.     Rect            destRect;
  621.     
  622.     GetPort (&savedPort);
  623.     SetPort ((WindowPtr) logWindow);
  624.     
  625.     tTELite = logWindow->fTELiteHandle;
  626.     tBitMap = ((**tTELite).offScreenPort)->portBits;
  627.     
  628.     GetTERect ((WindowPtr) logWindow, &destRect);
  629.     offScreenRect = tBitMap.bounds;
  630.     offScreenRect.top = (**tTELite).top;
  631.     offScreenRect.left = (**tTELite).left;
  632.     
  633.     if ((offScreenRect.bottom-offScreenRect.top) > (destRect.bottom-destRect.top))
  634.         offScreenRect.bottom = offScreenRect.top + destRect.bottom-destRect.top;
  635.     else
  636.         destRect.bottom = destRect.top + offScreenRect.bottom-offScreenRect.top;
  637.         
  638.     if ((offScreenRect.right-offScreenRect.left) > (destRect.right-destRect.left))
  639.         offScreenRect.right = offScreenRect.left + destRect.right-destRect.left;
  640.     else
  641.         destRect.right = destRect.left + offScreenRect.right-offScreenRect.left;
  642.         
  643.     
  644.     CopyBits (&tBitMap, &((WindowPtr) logWindow)->portBits, &offScreenRect,
  645.             &destRect, srcCopy, nil);
  646.             
  647.     SetPort (savedPort);
  648. }
  649.  
  650.  
  651. #pragma segment LogWindowSeg
  652. void    DrawLogWindow (WindowPtr theWindow)
  653. {
  654.     WindowPtr        savedPort;
  655.     Rect            cntlRect = (**((LogWindowPtr) theWindow)->saveCheckBox).contrlRect;
  656.     char             cString[kStrBufferSize];
  657.     char            savedState;
  658.     FSSpecHandle    tFSSpecHandle;
  659.     
  660.     GetPort (&savedPort);
  661.     SetPort (theWindow);
  662.     
  663.     EraseRect(&theWindow->portRect);
  664.     UpdtControl (theWindow, theWindow->visRgn);
  665.     
  666.     ShowGrowIcon (theWindow);
  667.     
  668.     DrawFromOffscreen ((LogWindowPtr) theWindow);
  669.     
  670.     getindstring (cString, rLogWindowIndSTR, kSaveToDiskInd);
  671.     MoveTo (cntlRect.right, cntlRect.bottom - 5);
  672.     
  673.     tFSSpecHandle = ((LogWindowPtr) theWindow)->logFileSpec;
  674.     if (tFSSpecHandle != nil) {
  675.         savedState = HGetState((Handle) tFSSpecHandle);
  676.         HLock((Handle) tFSSpecHandle);
  677.         
  678.         (void) strncat (cString, (char *) (**tFSSpecHandle).name+1, (**tFSSpecHandle).name[0]);
  679.         
  680.         HSetState((Handle) tFSSpecHandle, savedState);
  681.     }
  682.     
  683.     if (theWindow != FrontWindow())
  684.         TextMode (grayishTextOr);
  685.         
  686.     drawstring (cString);
  687.     TextMode (srcOr);
  688.     
  689.     MoveTo (0, kTopMargin-1); Line ((theWindow->portRect.right - theWindow->portRect.left), 0);
  690.     MoveTo (0, kTopMargin-3); Line ((theWindow->portRect.right - theWindow->portRect.left), 0);
  691.     
  692.     SetPort (savedPort);
  693. }
  694.  
  695.  
  696. #pragma segment LogWindowSeg
  697. void    DoLogWindowActivate (WindowPtr theWindow, Boolean becomingActive)
  698. {
  699.     WindowPtr        savedPort;
  700.     Rect            nameRect;
  701.     
  702.     GetPort (&savedPort);
  703.     SetPort (theWindow);
  704.     
  705.     HiliteControl (((LogWindowPtr) theWindow)->clearLogButton, (becomingActive)?0:0xFF);
  706.     
  707.     if (becomingActive) 
  708.         ShowControl(((LogWindowPtr) theWindow)->vScroll);
  709.     else
  710.         HideControl(((LogWindowPtr) theWindow)->vScroll);
  711.  
  712.     ShowGrowIcon (theWindow);
  713.     
  714.     nameRect = (theWindow)->portRect;
  715.     nameRect.bottom = nameRect.top + kTopMargin - 3;
  716.     nameRect.left += (*(((LogWindowPtr) theWindow)->saveCheckBox))->contrlRect.right;
  717.     InvalRect (&nameRect);
  718.         
  719.     SetPort (savedPort);
  720. }
  721.  
  722.  
  723. #pragma segment LogWindowSeg
  724. void    DoLogWindowUpdate (WindowPtr theWindow)
  725. {
  726.     BeginUpdate (theWindow);    
  727.     if ( ! EmptyRgn (theWindow->visRgn) )
  728.     {
  729.         DrawLogWindow (theWindow);
  730.     }
  731.     EndUpdate (theWindow);
  732. }
  733.  
  734.  
  735. #pragma segment LogWindowSeg
  736. void    AdjustHeight (short * height, LogWindowPtr    logWindow)
  737. {
  738.     short lh = (**(logWindow)->fTELiteHandle).lineHeight;
  739.     
  740.     *height = ((*height - kTopMargin) / lh) * lh + kTextMargin + kTextMargin + kTopMargin;
  741. }
  742.  
  743.  
  744. #pragma segment LogWindowSeg
  745. void DoLogWindowGrow (WindowPtr theWindow, const EventRecord * theEvent)
  746. {
  747.     long        growResult;
  748.     Rect        growRect, screenRect;
  749.     WindowPtr    savedPort;
  750.     TELitePtr    theTELite;
  751.     RgnHandle    grayRgn = GetGrayRgn ();
  752.     
  753.     screenRect = (*grayRgn)->rgnBBox;
  754.     
  755.     theTELite = *((LogWindowPtr)theWindow)->fTELiteHandle;
  756.     
  757.     growRect = theTELite->offScreenPort->portBits.bounds;
  758.     growRect.bottom += kTextMargin + kTextMargin + 1 + kTopMargin;
  759.     growRect.right += kTextMargin + kTextMargin + 17;
  760.     
  761.     if ((growRect.bottom-growRect.top) > (screenRect.bottom-screenRect.top))
  762.         growRect.bottom = growRect.top + screenRect.bottom-screenRect.top;
  763.         
  764.     if ((growRect.right-growRect.left) > (screenRect.right-screenRect.left))
  765.         growRect.right = growRect.left + screenRect.right-screenRect.left;
  766.  
  767.     growRect.left = theTELite->minWidth;
  768.     growRect.top = 5 * theTELite->lineHeight + kTextMargin + kTextMargin + kTopMargin;        // allow to shrink window down to 5 lines
  769.     
  770.     growResult = GrowWindow (theWindow, theEvent->where, &growRect);
  771.     
  772.     if ( growResult != 0 ) {
  773.         short height = HiWord(growResult);
  774.         AdjustHeight (&height, (LogWindowPtr) theWindow);
  775.         SizeWindow (theWindow, LoWord(growResult), height, true);
  776.         AdjustScrollbars ((LogWindowPtr) theWindow, true);
  777.         
  778.         GetPort (&savedPort);
  779.         SetPort (theWindow);
  780.         InvalRect (&theWindow->portRect);
  781.         SetPort (savedPort);
  782.     }
  783. }
  784.  
  785.  
  786. #pragma segment LogWindowSeg
  787. void DoLogWindowZoom (WindowPtr theWindow, short zoomDirection)
  788. {
  789.     WindowPtr    savedPort;
  790.     Rect        zoomRect;
  791.     TELitePtr    theTELite;
  792.     short        height;
  793.     
  794.     GetPort (&savedPort);
  795.     SetPort (theWindow);
  796.  
  797.     theTELite = *((LogWindowPtr)theWindow)->fTELiteHandle;
  798.     zoomRect = theTELite->offScreenPort->portBits.bounds;
  799.     zoomRect.bottom += kTextMargin + kTextMargin + kTopMargin;
  800.     zoomRect.right += kTextMargin + kTextMargin + 16;
  801.     
  802.     ZoomWindowInCurrentDevice (theWindow, zoomRect.right - zoomRect.left,
  803.             zoomRect.bottom - zoomRect.top, zoomDirection, theWindow == FrontWindow());
  804.     
  805.     zoomRect = theWindow->portRect;
  806.     height = zoomRect.bottom - zoomRect.top;
  807.     AdjustHeight (&height, (LogWindowPtr) theWindow);
  808.     SizeWindow (theWindow, zoomRect.right - zoomRect.left, height, true);
  809.     AdjustScrollbars ((LogWindowPtr) theWindow, true);
  810.  
  811.     InvalRect (&theWindow->portRect);    
  812.     SetPort (savedPort);
  813. }
  814.  
  815.  
  816. #pragma segment LogWindowSeg
  817. void    ShowGrowIcon (WindowPtr    theWindow)
  818. {
  819.     RgnHandle    savedClipRgn;
  820.     Rect        growIconRect;
  821.     WindowPtr    savedPort;
  822.     
  823.     GetPort (&savedPort);
  824.     SetPort (theWindow);
  825.     savedClipRgn = NewRgn ();
  826.     GetClip (savedClipRgn);
  827.     growIconRect = theWindow->portRect;
  828.     growIconRect.top += kTopMargin;
  829.     growIconRect.left = growIconRect.right - 15;
  830.     ClipRect (&growIconRect);
  831.     DrawGrowIcon(theWindow);
  832.     SetClip (savedClipRgn);
  833.     DisposeRgn (savedClipRgn);
  834.     SetPort (savedPort);
  835. }
  836.  
  837.  
  838. #pragma segment LogWindowSeg
  839. void    AppendLine (LogWindowPtr logWindow, const char * cStr)
  840. {
  841.     FSSpec    tFSSpec;
  842.     OSErr    errCode;
  843.     short     refNum;
  844.     char    endln = '\n';
  845.     long    count = strlen (cStr);
  846.     
  847.     tFSSpec = **logWindow->logFileSpec;
  848.  
  849.     errCode = FSpOpenDF (&tFSSpec, fsRdWrPerm, &refNum);
  850.     if (errCode == noErr) {
  851.         errCode = SetFPos (refNum, fsFromLEOF, 0);
  852.         errCode = FSWrite (refNum, &count, cStr);
  853.         
  854.         count = 1;
  855.         errCode = FSWrite (refNum, &count, &endln);
  856.         
  857.         errCode = FSClose (refNum);
  858.         errCode = FlushVol (nil, tFSSpec.vRefNum);
  859.     } 
  860.     else {
  861.         logWindow->saveToDisk = false;
  862.         SetCtlValue (logWindow->saveCheckBox, false);
  863.         PutLine (logWindow, "### FSpOpenDF failed, OSErr = %d", errCode);
  864.         DisposHandle ((Handle) logWindow->logFileSpec);
  865.         logWindow->logFileSpec = nil;
  866.     }
  867. }
  868.  
  869.  
  870. #pragma segment LogWindowSeg
  871. void    VPutLine (LogWindowPtr logWindow, const char * format, va_list ap)
  872. {
  873.     char    cStr[kStrBufferSize];
  874.     long     len;
  875.     
  876.     if (logWindow != nil) {
  877.         len = vsprintf ((char *) cStr, format, ap);
  878.         
  879.         PutTextToLogWindow (logWindow, cStr);
  880.     }
  881. }
  882.  
  883.  
  884. #pragma segment LogWindowSeg
  885. void    PutLine (LogWindowPtr logWindow, const char * format, ...)
  886. {
  887.     va_list        ap;
  888.     char        cStr[kStrBufferSize];
  889.     long        len;
  890.     
  891.     if (logWindow != nil) {
  892.         va_start (ap, format);
  893.         len = vsprintf ((char *) cStr, format, ap);
  894.         va_end (ap);
  895.         
  896.         PutTextToLogWindow (logWindow, cStr);
  897.     }
  898. }
  899.  
  900.  
  901. #pragma segment LogWindowSeg
  902. void PutTextToLogWindow (LogWindowPtr logWindow, const char * cStr)
  903. {
  904.     WindowPtr        savedPort;
  905.     TELiteHandle    tTELite;
  906.     short            max, value;
  907.     
  908.         tTELite = logWindow->fTELiteHandle;
  909.         GetPort (&savedPort);
  910.         SetPort ((**tTELite).offScreenPort);
  911.         
  912.         if ((**tTELite).numOfLines < (**tTELite).maxLines) {
  913.             MoveTo (0, (**tTELite).numOfLines * (**tTELite).lineHeight + (**tTELite).fontAscent);
  914.             ++(**tTELite).numOfLines;
  915.         }
  916.         else {
  917.             RgnHandle updateRgn = NewRgn ();
  918.             ScrollRect (&((**tTELite).offScreenPort)->portRect, 0, -(**tTELite).lineHeight, updateRgn);
  919.             MoveTo (0, ((**tTELite).maxLines-1) * (**tTELite).lineHeight + (**tTELite).fontAscent);
  920.             DisposeRgn (updateRgn);
  921.         }
  922.         
  923.         drawstring (cStr);
  924.         
  925.         AdjustScrollbars (logWindow, false);
  926.         
  927.         max = GetCtlMax (logWindow->vScroll);
  928.         value = GetCtlValue (logWindow->vScroll);
  929.         if ((max != 0) && (value < max)) {
  930.             SetCtlValue (logWindow->vScroll, max);
  931.             (**tTELite).top = max * (**tTELite).lineHeight;
  932.         }
  933.         
  934.         DrawFromOffscreen (logWindow);
  935.         
  936.         SetPort (savedPort);
  937.         
  938.         if (logWindow->saveToDisk)
  939.             AppendLine (logWindow, cStr);
  940. }
  941.  
  942.  
  943. #pragma segment LogWindowSeg
  944. void    PutCLine (LogWindowPtr logWindow, long color, const char * format, ...)
  945. {
  946.     va_list            ap;
  947.     char            cStr[kStrBufferSize];
  948.     long            len;
  949.     WindowPtr        savedPort;
  950.     TELiteHandle    tTELite;
  951.     short            max, value;
  952.     
  953.     if (logWindow != nil) {
  954.         va_start (ap, format);
  955.         len = vsprintf ((char *) cStr, format, ap);
  956.         va_end (ap);
  957.         
  958.         tTELite = logWindow->fTELiteHandle;
  959.         GetPort (&savedPort);
  960.         SetPort ((**tTELite).offScreenPort);
  961.         ForeColor (color);
  962.         
  963.         if ((**tTELite).numOfLines < (**tTELite).maxLines) {
  964.             MoveTo (0, (**tTELite).numOfLines * (**tTELite).lineHeight + (**tTELite).fontAscent);
  965.             ++(**tTELite).numOfLines;
  966.         }
  967.         else {
  968.             RgnHandle updateRgn = NewRgn ();
  969.             ScrollRect (&((**tTELite).offScreenPort)->portRect, 0, -(**tTELite).lineHeight, updateRgn);
  970.             MoveTo (0, ((**tTELite).maxLines-1) * (**tTELite).lineHeight + (**tTELite).fontAscent);
  971.             DisposeRgn (updateRgn);
  972.         }
  973.         
  974.         drawstring (cStr);
  975.         
  976.         AdjustScrollbars (logWindow, false);
  977.         
  978.         max = GetCtlMax (logWindow->vScroll);
  979.         value = GetCtlValue (logWindow->vScroll);
  980.         if ((max != 0) && (value < max)) {
  981.             SetCtlValue (logWindow->vScroll, max);
  982.             (**tTELite).top = max * (**tTELite).lineHeight;
  983.         }
  984.         
  985.         DrawFromOffscreen (logWindow);
  986.         
  987.         ForeColor (blackColor);
  988.         SetPort (savedPort);
  989.         
  990.         if (logWindow->saveToDisk)
  991.             AppendLine (logWindow, cStr);
  992.     }
  993. }
  994.  
  995.  
  996. #pragma segment LogWindowSeg
  997. void    TELiteScroll (LogWindowPtr logWindow, short amount)
  998. {
  999.     TELiteHandle    tTELite;
  1000.     
  1001.     tTELite = logWindow->fTELiteHandle;
  1002.     (**tTELite).top -= amount * (**tTELite).lineHeight;
  1003.     
  1004.     DrawFromOffscreen (logWindow);
  1005. }
  1006.  
  1007.  
  1008. #pragma segment LogWindowSeg
  1009. void AdjustScrollbars (LogWindowPtr logWindow, Boolean needsResize)
  1010. {
  1011. #define kControlInvisible        0
  1012. #define kControlVisible            0xFF
  1013.  
  1014. //    (*logWindow->vScroll)->contrlVis = kControlInvisible;
  1015.     
  1016.     if ( needsResize )
  1017.         AdjustScrollSizes (logWindow);
  1018.     AdjustScrollValues (logWindow, needsResize);
  1019.     
  1020. //    (*logWindow->vScroll)->contrlVis = kControlVisible;
  1021. }
  1022.  
  1023.  
  1024. #pragma segment LogWindowSeg
  1025. void AdjustScrollSizes (LogWindowPtr logWindow)
  1026. {
  1027.     MoveControl(logWindow->vScroll, ((WindowPtr)logWindow)->portRect.right - 15, kTopMargin-1);
  1028.     SizeControl(logWindow->vScroll, 16, (((WindowPtr)logWindow)->portRect.bottom - 
  1029.                 ((WindowPtr)logWindow)->portRect.top) - 13 - kTopMargin);
  1030. }
  1031.  
  1032.  
  1033. #pragma segment LogWindowSeg
  1034. void    GetTERect (WindowPtr theWindow, Rect * theRect)
  1035. {
  1036.     *theRect = theWindow->portRect;
  1037.     InsetRect (theRect, kTextMargin, kTextMargin);
  1038.     theRect->top += kTopMargin;
  1039.     theRect->right -= 15;
  1040. }
  1041.  
  1042.  
  1043. #pragma segment LogWindowSeg
  1044. void AdjustScrollValues (LogWindowPtr logWindow, Boolean canRedraw)
  1045. {
  1046.     AdjustHV(true, logWindow->vScroll, logWindow->fTELiteHandle, canRedraw);
  1047. }
  1048.  
  1049.  
  1050. #pragma segment LogWindowSeg
  1051. void AdjustHV (Boolean isVert, ControlHandle control, TELiteHandle theTELite, Boolean canRedraw)
  1052. {
  1053. #pragma unused (isVert)
  1054.  
  1055.     short        value, max;
  1056.     short        oldValue, oldMax;
  1057.     TELitePtr    te;
  1058.     Rect        viewRect;
  1059.     
  1060.     GetTERect ((*control)->contrlOwner, &viewRect);
  1061.  
  1062.     oldValue = GetCtlValue (control);
  1063.     oldMax = GetCtlMax (control);
  1064.     te = *theTELite;
  1065.     
  1066.     max = te->numOfLines - ((viewRect.bottom - viewRect.top) /
  1067.                 te->lineHeight);
  1068.     
  1069.     if ( max <= 0 ) {
  1070.         max = 0;
  1071.         te->top = 0;
  1072.     } else {            // max > 0
  1073.         if (te->top != max * te->lineHeight)
  1074.             te->top = max * te->lineHeight;
  1075.     }
  1076.     
  1077.     SetCtlMax (control, max);
  1078.     
  1079.     te = *theTELite;
  1080.     value = te->top / te->lineHeight;
  1081.     
  1082.     if ( value < 0 ) value = 0;
  1083.     else if ( value >  max ) value = max;
  1084.  
  1085.     SetCtlValue(control, value);
  1086.  
  1087.     if ( (*control)->contrlVis && (canRedraw || (max != oldMax) || (value != oldValue)) )
  1088.         ShowControl(control);
  1089. }
  1090.  
  1091.  
  1092. #pragma segment LogWindowSeg
  1093. void    ClearLogWindow (LogWindowPtr logWindow)
  1094. {
  1095.     WindowPtr        savedPort;
  1096.     Rect            tRect;
  1097.     TELiteHandle    teHand = logWindow->fTELiteHandle;
  1098.     
  1099.     SetCtlValue (logWindow->vScroll, 0);
  1100.     SetCtlMax (logWindow->vScroll, 0);
  1101.     
  1102.     (*teHand)->top = (*teHand)->left = (*teHand)->numOfLines = 0;
  1103.     
  1104.     GetPort (&savedPort);
  1105.     SetPort ((*teHand)->offScreenPort);
  1106.     EraseRect (&(*teHand)->offScreenPort->portRect);
  1107.     
  1108.     SetPort ((WindowPtr) logWindow);
  1109.     GetTERect ((WindowPtr) logWindow, &tRect);
  1110.     InvalRect (&tRect);
  1111.     SetPort (savedPort);
  1112. }
  1113.  
  1114.  
  1115.